from crc import crc8 
# # 示例输入参数
# control_byte = bytes.fromhex('C0')  # 假设控制域字节
# seq = 0x01  # SEQ序列
# afn = 0x02  # 应用层功能码AFN
# address = "00000000000001" # 源地址DA，小端模式
# di = 0x00000001  # 数据标识DI，小端模式
# da = 0x0001  # 数据地址DA，小端模式
# user_data = bytes.fromhex('02700000001000e0110101583209170424')  # 用户数据

# # 构建帧
# frame = build_frame(control_byte, seq, afn, di, da, address, user_data)
# print(f"Built frame: {frame.hex()}")

def build_seq(seq_info):
    """
    根据提供的SEQ信息字典构建单个字节的SEQ值。

    :param seq_info: 包含SEQ各部分信息的字典。
    :return: 构建出的SEQ字节。
    """
    # 检查输入字典是否包含必要的键
    required_keys = {"TpV", "FIR", "FIN", "CON", "PSEQ/RSEQ"}
    if not required_keys.issubset(seq_info.keys()):
        raise ValueError("Input dictionary must contain all required keys")

    # 从字典中提取各部分的值
    tpv = seq_info["TpV"]
    fir = seq_info["FIR"]
    fin = seq_info["FIN"]
    con = seq_info["CON"]
    pseq_rseq = seq_info["PSEQ/RSEQ"]

    # 确保各部分的值是0或1
    if not (tpv in [0, 1] and fir in [0, 1] and fin in [0, 1] and con in [0, 1] and 0 <= pseq_rseq <= 15):
        raise ValueError("Invalid values in seq_info dictionary")

    # 构建SEQ字节
    seq_byte = (tpv << 7) | (fir << 6) | (fin << 5) | (con << 4) | pseq_rseq

    # 将构建的整数转换为单个字节
    seq = seq_byte.to_bytes(1, byteorder='big')

    return seq

def build_control_field(control_info):
    """
    根据提供的控制域信息字典构建控制域的字节。

    :param control_info: 包含控制域各部分信息的字典。
    :return: 构建出的控制域字节。
    """
    # 检查输入字典是否包含必要的键
    # required_keys = {"DIR", "PRM", "FCB", "FCV", "Function Code"}
    # if not required_keys.issubset(control_info.keys()):
    #     raise ValueError("Input dictionary must contain all required keys")

    # 从字典中提取各部分的值
    dir_bit = control_info["DIR"]
    prm_bit = control_info["PRM"]
    fcb_bit = control_info["FCB"]
    fcv_bit = control_info["FCV"]
    function_code = control_info["Function Code"]

    # # 确保各部分的值是0或1
    # if not (dir_bit in [0, 1] and prm_bit in [0, 1] and fcb_bit in [0, 1] and fcv_bit in [0, 1] and 0 <= function_code <= 7):
    #     raise ValueError("Invalid values in control_info dictionary")

    # 构建控制域字节
    control_byte = (dir_bit << 7) | (prm_bit << 6) | (fcb_bit << 5) | (fcv_bit << 4) | function_code

    # 将构建的整数转换为单个字节
    control_field = control_byte.to_bytes(1, byteorder='big')

    return control_field
'''
 {
    'User Data Info': 
    {
        'AFN': '02', 
        'SEQ': '70', 
        'SEQINFO': 
        {
            'TpV': 0, 
            'FIR': 1, 
            'FIN': 1, 
            'CON': 1, 
            'PSEQ/RSEQ': 0
        }, 
        'DA':'0000', 
        'DI': 'E0001000', 
        'Data': '110101583209170424'
    }
}
'''
def build_user_data(frame_info):
    """
    根据提供的用户数据区信息字典构建用户数据区的字节串。

    :param frame_info: 包含用户数据区各部分信息的字典。
    :return: 构建出的用户数据区字节串。
    """
    # 检查输入字典是否包含必要的键
    # required_keys = {"AFN", "SEQ", "DA", "DI", "Data"}
    # if not required_keys.issubset(frame_info.keys()):
    #     raise ValueError("Input dictionary must contain all required keys")

    # 从字典中提取各部分的值
    afn_hex = frame_info["AFN"]
    seq_hex = build_seq(frame_info["SEQINFO"])
    da_hex = frame_info["DA"]
    di_str = frame_info["DI"]
    data_hex = frame_info["Data"]

    # 将十六进制字符串转换回字节
    afn = bytes.fromhex(afn_hex)
    seq = seq_hex
    da = bytes.fromhex(da_hex)
    di = int(di_str, 16).to_bytes(4, byteorder='little')
    data = bytes.fromhex(data_hex)

    # 构建用户数据区字节串
    user_data = afn + seq + da + di + data

    return user_data


def build_frame(frame_info):
    """
    根据提供的帧信息字典构建通信规约帧的字节串。

    :param frame_info: 包含帧信息的字典。
    :return: 构建出的原始帧的字节串。
    """
    # 帧结构定义
    frame_structure = {
        "start_char": 0x68,
        "length": 2,  # 字节长度
        "control_field": 1,  # 字节长度
        "address_field": 7,  # 字节长度
        "checksum": 1,  # 字节长度
        "end_char": 0x16,
    }

    # 构建起始字符
    start_char = bytes([frame_structure["start_char"]])

    # 构建控制域
    control_field = build_control_field(frame_info["Control Field Info"])
    # print("control_field: ", control_field.hex())
    # control_field = bytes.fromhex(frame_info["Control Field Info"]["AFN"] + frame_info["Control Field Info"]["SEQ"] + frame_info["Control Field Info"]["DA"] + frame_info["Control Field Info"]["DI"])
    
    # 构建地址域
    address_field = bytes.fromhex(frame_info["Address Field"])
    # print("address_field:", address_field.hex())

    # 构建用户数据区
    user_data = build_user_data(frame_info["User Data Info"])
    # print("user_data:", user_data.hex())

    # 构建结束字符
    end_char = bytes([frame_structure["end_char"]])

    crc_data = control_field + address_field + user_data
    # print(crc_data.hex())

    # 计算用户数据区长度（不包括地址域、控制域和校验和）
    user_data_length = len(user_data)  # 每个字节两个十六进制字符
    total_length = int(user_data_length + 8)  # 用户数据区长度 + 帧头（8字节）
    # 构建长度字段（小端字节序）
    length_bytes = total_length.to_bytes(frame_structure["length"], byteorder='little')

    # 构建校验和字段（这里暂时填充为0，实际中需要根据协议计算）
    checksum = bytes([ crc8(crc_data) ])
    raw_frame = start_char + length_bytes + length_bytes + bytes([0x68])  + crc_data + checksum + end_char
    # print(raw_frame.hex())
    return raw_frame

userdata = { 
        'AFN': '02', 
        'SEQ': '70', 
        'SEQINFO': 
        {
            'TpV': 0, 
            'FIR': 1, 
            'FIN': 1, 
            'CON': 1, 
            'PSEQ/RSEQ': 0
        }, 
        'DA':'0000', 
        'DI': 'E0001000', 
        'Data': '110101583209170424'
    } 

def build_confirmation_frame(is_ok = True, seq = '00',  dir = 0, ):
    frame_info = {'Start Character': 104, 'Length': 25, 
                  'Control Field Info': {'DIR': dir, 'PRM': 0, 'FCB': 0, 'FCV': 0, 'Function Code': 0}, 
                  'Address Field': '11110001000000',  
                  'User Data Info': {'AFN': '00', 'SEQ': seq, 
                                     'SEQINFO': {'TpV': 0, 'FIR': 1, 'FIN': 1, 'CON': 1, 'PSEQ/RSEQ': 0}, 
                                     'DA': '0000', 'DI': 'E0000000', 'Data': '00'}, 
                                     'Checksum': '3316', 'End Character': 22
                                     } 
 
    if( not is_ok):
        frame_info["User Data Info"]["Data"] = '00'
    f = build_frame(frame_info)
    return f

def build_read_param(di=''):
    frame_info = {'Start Character': 104, 'Length': 25, 
                  'Control Field Info': {'DIR': 0, 'PRM': 1, 'FCB': 0, 'FCV': 0, 'Function Code': 0}, 
                  'Address Field': '11110001000000',  
                  'User Data Info': {'AFN': '0A', 'SEQ': 'seq', 
                                     'SEQINFO': {'TpV': 0, 'FIR': 1, 'FIN': 1, 'CON': 1, 'PSEQ/RSEQ': 0}, 
                                     'DA': '0000', 'DI': di, 'Data': ''}, 
                                     'Checksum': '3316', 'End Character': 22
                                     } 
  
    f = build_frame(frame_info)
    return f

if __name__ == '__main__': 
    # pass
    # d = build_user_data(userdata)
    # print(d.hex())

    # c = build_control_field({'DIR': 1, 'PRM': 1, 'FCB': 0, 'FCV': 0, 'Function Code': 1})
    # print(c.hex())

    # f = build_confirmation_frame()
    # print(f.hex())
    f = build_read_param('E000010F')
    print(f.hex())